package handlers

import (
	"fmt"

	captcha "../lib/captcha"
	rpc "../lib/jsonrpc2"
	jwt "../lib/jwt"
	log "../lib/log"
	mod "../models"
)

// UserGetCaptcha ...
/**
	*
	* @api {post} UserGetCaptcha 1. 获取图片验证码
	* @apiVersion 1.0.0
	* @apiGroup User
	* @apiDescription
	* 获取图片验证码
	*
	* @apiParamExample {json} 请求示例
{
	"jsonrpc": "2.0",
	"method": "UserGetCaptcha",
	"params": null,
	"id": "1"
}
	* @apiSuccess idkey 验证码对应的idkey
	* @apiSuccess base64 base64形式的验证图片
	* @apiSuccessExample {json} 返回示例
{
    "jsonrpc": "2.0",
    "result": {
        "idkey": "GV7EYQQNeMSgTqGCutEH"
        "base64" : "......"
    },
    "error": null,
    "id": "1"
}
	*
	* @apiError -32000 Invalid Mobile
	* @apiErrorExample {json} 错误示例
{
    "jsonrpc": "2.0",
    "result": null,
    "error": {
        "code": -32000,
        "message": "Invalid Mobile"
    },
    "id": "1"
}
*/
func UserGetCaptcha(params map[string]interface{}) (result interface{}, error interface{}) {

	idkey, base64, e := captcha.NewCaptcha()
	if e != nil {
		error = rpc.InternalError
		log.Error(e)
		return
	}

	type res struct {
		Idkey  string `json:"idkey"`
		Base64 string `json:"base64"`
	}
	result = &res{idkey, base64}

	return
}

// UserGetSignupMobileCode ...
/**
*
* @api {post} UserGetSignupMobileCode 2. 手机号获取注册验证码
* @apiVersion 1.0.0
* @apiGroup User
* @apiDescription
* 手机号获取注册验证码
*
* @apiParam {String} mobile 手机号
* @apiParam {String} idkey 上一步获取的图形验证码idkey
* @apiParam {String} cap  用户输入的图形验证码
*
* @apiSuccess {String} token 验证码对应的token，下一步验证使用 该token 1分钟失效
*
* @apiError -32000 Invalid Mobile
* @apiError -32000 Invalid Captcha
* @apiError -32000 Invalid Token
 */
func UserGetSignupMobileCode(params map[string]interface{}) (result interface{}, error interface{}) {

	if params["mobile"] == nil ||
		params["idkey"] == nil ||
		params["cap"] == nil {
		error = toRPCError(ErrMissingParams)
	}

	mobile := params["mobile"].(string)
	idkey := params["idkey"].(string)
	cap := params["cap"].(string)

	if !IsVaildMobile(mobile) {
		error = toRPCError(ErrInvalidMobile)
		return
	}

	if !captcha.VerifyCaptcha(idkey, cap) {
		error = toRPCError(ErrInvalidCaptcha)
		return
	}

	token, err := jwt.NewMobileCodeToken(GenCode(), mobile)
	//token, err := jwt.NewMobileCodeToken("000000", mobile)
	if err != nil {
		error = &rpc.InternalError
		fmt.Println(err)
		return
	}

	type res struct {
		Token string `json:"token"`
	}
	result = &res{token}

	return
}

// UserSignupByMobileCodePass ...
/**
	*
	* @api {post} UserSignupByMobileCodePass 3. 通过手机、验证码、密码完成注册
	* @apiVersion 1.0.0
	* @apiGroup User
	* @apiDescription
	* 通过手机、验证码、密码完成注册
	*
	* @apiParam {String} token  中返回的token
	* @apiParam {String} mobile 手机号
	* @apiParam {String} code 	验证码
	* @apiParam {String} pass   密码
	* @apiParamExample {json} 请求示例
{
	"jsonrpc": "2.0",
	"method": "UserSignupByMobileCodePass",
	"params": {
		"mobile": "15061519072",
		"token": "eyJhbGciOiJI...",
		"code": "339023",
		"pass": "9928jjsduwq"
	},
	"id": "1"
}
	*
	* @apiSuccessExample {json} 返回示例
{
    "jsonrpc": "2.0",
    "result": "success",
    "error": null,
    "id": "1"
}
	*
	* @apiError -32000 Invalid Mobile
	* @apiErrorExample {json} 错误示例
{
    "jsonrpc": "2.0",
    "result": null,
    "error": {
        "code": -32000,
        "message": "Invalid Mobile"
    },
    "id": "1"
}
*/
func UserSignupByMobileCodePass(params map[string]interface{}) (result interface{}, error interface{}) {

	var (
		mobile string
		token  string
		code   string
		pass   string
	)

	if params["mobile"] != nil {
		mobile = params["mobile"].(string)
	}

	if params["token"] != nil {
		token = params["token"].(string)
	}

	if params["code"] != nil {
		code = params["code"].(string)
	}

	if params["pass"] != nil {
		pass = params["pass"].(string)
	}

	if !IsVaildMobile(mobile) {
		error = toRPCError(ErrInvalidMobile)
		return
	}

	if pass == "" {
		error = rpc.InvalidParams
		return
	}

	//后门 不判断 code 和 token
	if params["door"].(string) == "I use a back door here" {

	} else {

		if token == "" || code == "" {
			error = rpc.InvalidParams
			return
		}

		tmobile, tcode, err := jwt.ParseMobileCodeToken(token)
		if err != nil {
			error = toRPCError(ErrInvalidToken)
			return
		}

		if tmobile != mobile {
			error = toRPCError(ErrMobileNotMatches)
			return
		}

		if tcode != code {
			error = toRPCError(ErrCodeNotMatches)
			return
		}
	}

	nu, err := mod.CreateUserByMobile(mobile, pass)

	if err == mod.ErrNotFound {
		error = toRPCError(ErrMobileExisted)
		return
	}

	if err == mod.ErrExisted {
		error = toRPCError(ErrMobileExisted)
		return
	}

	if err != nil {
		error = toRPCError(err)
		log.Error(err)
		return
	}

	log.Success("New User Signed up:\n	%+v\n", nu)

	result = "success"

	return
}

// UserSigninByMobilePass ...
/**
*
* @api {post} UserSigninByMobilePass 3. 通过手机、密码登录
* @apiVersion 1.0.0
* @apiGroup User
* @apiDescription
* 通过手机、密码登录
*
* @apiParam {String} mobile 手机号
* @apiParam {String} pass   密码
*
* @apiSuccess {String} token 验证用的token
* @apiSuccess {String} nickname 昵称
* @apiSuccess {String} avatar80
* @apiSuccess {String} avatar50
* @apiSuccess {String} avatar30
*
* @apiError -32000 Invalid Mobile
 */
func UserSigninByMobilePass(params map[string]interface{}) (result interface{}, error interface{}) {
	var mobile, pass string

	if params["mobile"] == nil ||
		params["pass"] == nil {
		error = rpc.InvalidParams
		return
	}

	mobile = params["mobile"].(string)
	pass = params["pass"].(string)

	user, e := mod.GetUserByMobileAndPass(mobile, pass)

	if e != nil {
		if e == mod.ErrNotFound {
			error = toRPCError(ErrWrongUserOrPass)
			return
		}
		error = newRPCError(e)
		return
	}

	token, e := jwt.NewToken(user.UUID)
	if e != nil {
		error = rpc.InternalError
		log.Error(e)
		return
	}

	type res struct {
		Token    string `json:"token"`
		Nickname string `json:"nickname"`
		Avatar80 string `json:"avatar80"`
		Avatar50 string `json:"avatar50"`
		Avatar30 string `json:"avatar30"`
	}

	result = &res{
		token,
		user.Nickname,
		string(user.Avatar80),
		string(user.Avatar50),
		string(user.Avatar30)}

	return
}

// UserUpdateBasicInfo ...
/**
*
* @api {post} UserUpdateBasicInfo 3.用户上传基本信息
* @apiVersion 1.0.0
* @apiGroup User
* @apiDescription
* 用上传基本信息
*
* @apiParam {String} token 用户token
* @apiParam {String} realname
* @apiParam {String} location
* @apiParam {String} gender
* @apiParam {String} birthdate 生日timestamp
* @apiParam {String} bloodtype
* @apiParam {String} introduction
*
* @apiSuccessExample {json} 返回示例
{
    "jsonrpc": "2.0",
    "result": "success",
    "error": null,
    "id": "1"
}
* @apiError -32000 Invalid Mobile
*/
func UserUpdateBasicInfo(params map[string]interface{}) (result interface{}, error interface{}) {

	if params["token"] == nil ||
		params["realname"] == nil ||
		params["location"] == nil ||
		params["gender"] == nil ||
		params["birthdate"] == nil ||
		params["bloodtype"] == nil ||
		params["introduction"] == nil {
		error = rpc.InvalidParams
		return
	}

	// 验证token
	token := params["token"].(string)
	uuid, e := jwt.ParseToken(token)
	if e != nil {
		error = rpc.InternalError
		log.Error(e)
		return
	}

	bi := &mod.BasicInfo{
		RealName:     params["realname"].(string),
		Location:     params["location"].(string),
		Gender:       params["gender"].(string),
		Birthdate:    params["birthdate"].(string),
		BloodType:    params["bloodtype"].(string),
		Introduction: params["introduction"].(string),
	}

	e = mod.UpdateUserBasicInfoByUUID(uuid, bi)
	if e != nil {
		error = rpc.InternalError
		log.Error(e)
		return
	}

	result = "success"
	return
}

// UserGetBasicInfo ...
/**
*
* @api {post} UserGetBasicInfo 3.用户上传基本信息
* @apiVersion 1.0.0
* @apiGroup User
* @apiDescription
* 用上传基本信息
*
* @apiParam {String} token 用户token
*
* @apiSuccessExample {json} 返回示例
{
    "jsonrpc": "2.0",
    "result": {

	},
    "error": null,
    "id": "1"
}
* @apiError -32000 Invalid Mobile
*/
func UserGetBasicInfo(params map[string]interface{}) (result interface{}, error interface{}) {

	if params["token"] == nil {
		error = rpc.InvalidParams
		return
	}

	// 验证token
	token := params["token"].(string)
	uuid, e := jwt.ParseToken(token)
	if e != nil {
		error = rpc.InternalError
		log.Error(e)
		return
	}

	bi, e := mod.GetUserBasicInfoByUUID(uuid)
	if e != nil {
		error = rpc.InternalError
		log.Error(e)
		return
	}

	result = bi
	return
}
